package dblayer;

import java.io.StringReader;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import entities.Authentication;
import entities.Customer;
import entities.Order;
import entities.OrderDetails;

public class CustomerDAO {

	EntityManagerFactory emf;
	EntityManager em;
	private static CustomerDAO instance;
	
	public CustomerDAO(){
		emf = Persistence.createEntityManagerFactory("CustomerData");
		
	}
	
	public static CustomerDAO getInstance(){
		if(instance==null){
			instance= new CustomerDAO();
			
		}
		return instance;
	}
	
	public String register(String fname,String lname,String street,String city,String state,String zipcode,String username,String password,String email) {
		em = emf.createEntityManager();
		Customer customerObj = new Customer();
		customerObj.setFirstName(fname);
		customerObj.setLastName(lname);
		customerObj.setStreet(street);
		customerObj.setState(state);
		customerObj.setCity(city);
		customerObj.setZipCode(zipcode);
		
		Authentication authenticationObj = new Authentication();
		authenticationObj.setCustomerUsername(username);
		authenticationObj.setPassword(password);
		authenticationObj.setEmailId(email);
		
		em.getTransaction().begin();
		em.persist(customerObj);
		authenticationObj.setCustomer(customerObj);
		em.persist(authenticationObj);
		em.getTransaction().commit();
		
		em.close();
		return "true";
	}
	
	/* (non-Javadoc)
	 * @see dblayer.CustomerDAOInterface#checkUsernameExists(java.lang.String)
	 */
	
	public String checkUsernameExists(String username){
		em = emf.createEntityManager();
		Authentication authenticateObj;
		authenticateObj=em.find(Authentication.class, username);
		if(authenticateObj!=null){
			return "true";
		}else{
			return "false";
		}
		
	}
	
	/* (non-Javadoc)
	 * @see dblayer.CustomerDAOInterface#authenticate(java.lang.String, java.lang.String)
	 */
	
	
	public String authenticate(String username, String password) {
		
		em = emf.createEntityManager();
		Authentication authenticateObj;
		authenticateObj=em.find(Authentication.class, username);
		if(authenticateObj!=null){
			if(authenticateObj.getPassword().equals(password)){
				return username;
			}else{
				return "false";
			}
			
		}else{
			return "false";
		}
		
	}

	/* (non-Javadoc)
	 * @see dblayer.CustomerDAOInterface#createOrder(java.lang.String)
	 */
	
	
	public String createOrder(String username) {
		int orderId;
		String currentUser;
		String generatedInvoiceXML= username;
		String invoiceXML="<?xml version=\"1.0\" encoding=\"UTF-8\"?><CustomerOrder>";
		
		try {
			
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	        DocumentBuilder db = dbf.newDocumentBuilder();
	        InputSource is = new InputSource();
	        is.setCharacterStream(new StringReader(username));

	        Document dom = db.parse(is);

			
			Element docEle = dom.getDocumentElement();
			
			
			currentUser=getTextValue(docEle, "UserID");
			
			em = emf.createEntityManager();
			Authentication authenticateObj;
			authenticateObj=em.find(Authentication.class, currentUser);
			orderId=-1;
			if(authenticateObj!=null){
				Order orderObj = new Order();
				orderObj.setCustomer(authenticateObj.getCustomer());
				em.getTransaction().begin();
				em.persist(orderObj);
				em.flush();
				em.refresh(orderObj);
				em.getTransaction().commit();
				orderId = orderObj.getOrderId();
				em.close();
				
				em = emf.createEntityManager();
				em.getTransaction().begin();
				OrderDetails orderDetails= new OrderDetails();
				orderDetails.setOrderId(orderId);
				orderDetails.setInvoice(generatedInvoiceXML);
				em.persist(orderDetails);
				em.getTransaction().commit();
				em.close();
			
			}else{
				return "PurchaseFailed";
			}
			
			invoiceXML +="<OrderID>"+Integer.valueOf(orderId).toString()+"</OrderID>";
			invoiceXML +="<UserID>"+currentUser+"</UserID>";
			invoiceXML += "<Items>";
			
			NodeList bikeNodes = docEle.getElementsByTagName("Bike");
			if(bikeNodes != null && bikeNodes.getLength() > 0) {
				for(int i = 0 ; i < bikeNodes.getLength();i++) {
					
					invoiceXML += "<Bike>";
					Element bike = (Element)bikeNodes.item(i);
					invoiceXML += "<Brand>"+getTextValueForTag(bike,"Brand")+"</Brand>";
					invoiceXML += "<Model>"+getTextValueForTag(bike,"Model")+"</Model>";
					invoiceXML += "<UnitPrice>"+getTextValueForTag(bike,"UnitPrice")+"</UnitPrice>";
					invoiceXML += "<Quantity>"+getTextValueForTag(bike,"Quantity")+"</Quantity>";
					invoiceXML += "</Bike>";
												
				}
			}
			invoiceXML += "</Items>";
			invoiceXML += "</CustomerOrder>";
			
		}catch (Exception e) {
			
			//System.out.println(e.getMessage());
		}
		//System.out.println(invoiceXML);
		return invoiceXML;
		
		
	}

	
	private String getTextValueForTag(Element ele, String tagName) {
		String textVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}

		return textVal;
	}
	
	private String getTextValue(Element ele,String tagName){
		String textVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}

		return textVal;
	}
	public String attachInvoice(String orderId,String invoiceId) {
		em=emf.createEntityManager();
		Order orderObj;
		orderObj = em.find(Order.class, Integer.valueOf(orderId).intValue());
		if(orderObj!=null){
			orderObj.setInvoiceId(Integer.valueOf(invoiceId).intValue());
			em.getTransaction().begin();
			orderObj.setInvoiceId(Integer.valueOf(invoiceId).intValue());
			em.getTransaction().commit();
			return "true";
		}else{
			return "false";
		}
		
	}

}
